#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "storage_helper.h"
#include "hlfs.h"

//uint64_t SEGMENT_SIZE_MASK;
//uint64_t SEGMENT_SIZE_SHIFT;
 
static gchar *location = NULL;
static gchar *fsname = NULL;
static gint block_size = 0;
static gint seg_size = 0;
static gboolean verbose = FALSE;
static GOptionEntry entries[] = {
	{"filesystem location",'l', 0, G_OPTION_ARG_STRING,   &location, "filesystem storage uri", "LOC"},
    	{"filesystme name", 'f', 0, G_OPTION_ARG_FILENAME, &fsname, "filesystem name", "NAME"},
    	{"filesystem block size", 'b', 0, G_OPTION_ARG_INT, &block_size, "filesystem block size", "BLOCKSIZE"},
    	{"filesystem segment size", 's', 0, G_OPTION_ARG_INT, &seg_size, "filesystem segment size", "SEGSIZE"},
    	{"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
    	{NULL}
};

static void 
error_func(GOptionContext *context, GOptionGroup *group, 
				gpointer data, GError **error) 
{
    if (*error && (*error)->message) {
        gchar *progname = g_get_prgname();
        g_print("%s: %s\nTry '%s --help' for more information.\n", 
				progname, (*error)->message, progname);
        exit(EXIT_FAILURE);
    }
}

/*  mkfs.lhfs -l local://<path> -f name */
/*  mkfs.lhfs -l http://<path>  -s name */

int 
main(int argc, char *argv[])
{
    GError *error = NULL;
    GOptionContext *context;
    context = g_option_context_new("- mkfs lhfs");
    g_option_context_add_main_entries(context, entries, NULL);
    g_option_context_set_help_enabled(context, TRUE);
    g_option_group_set_error_hook(g_option_context_get_main_group(context),
            					(GOptionErrorFunc)error_func);
    if (!g_option_context_parse(context, &argc, &argv, &error)) {
        g_print("option parsing failed: %s\n", error->message);
        exit(EXIT_FAILURE);
    }

    //g_print("location is :%s\n",location);
    //g_print("fsname   is :%s\n",fsname);
    //g_print("block size   is :%d\n",block_size);
    //g_print("segment size   is :%d\n",seg_size);

    struct back_storage *storage = init_storage_handler(location,fsname);
    if(NULL ==storage){
       g_print("can not get storage handler for uri:%s,fsname:%s\n",location,fsname);
       g_option_context_free(context);
       return -1;
    }

    if( 0!=storage->bs_file_mkdir(storage,NULL)){
        g_printf("can not mkdir:%s for our fs\n",fsname);
        g_option_context_free(context);
        return -1;
    }

#if 0
    gchar **v  = g_strsplit(location,"://",2);
    gchar *dir = v[1];
    //g_print("dir is %s\n",dir);
    char *fs_dir_path =  g_build_filename(dir,fsname,NULL);
    if (g_file_test(fs_dir_path, G_FILE_TEST_EXISTS)) {
        //g_return_if_fail(0==g_remove(fs_dir_path));
        g_printf("please remove dir :%s\n",fs_dir_path);
        return -1;
    }
    g_return_if_fail(0 == g_mkdir(fs_dir_path,0700));
#endif 

/*  uint64_t segment_size = seg_size;
    SEGMENT_SIZE_MASK  = segment_size - 1;
    SEGMENT_SIZE_SHIFT = 0;
    while (0 != (segment_size = (segment_size >> 1)))
    {                                                                                                         
        SEGMENT_SIZE_SHIFT++;
    }
*/
    GKeyFile *  sb_keyfile= g_key_file_new();
    g_key_file_set_string(sb_keyfile,"METADATA","fs_name",fsname);
    g_key_file_set_integer(sb_keyfile,"METADATA","block_size",block_size);
    g_key_file_set_integer(sb_keyfile,"METADATA","segment_size",seg_size);
    gchar *data = g_key_file_to_data(sb_keyfile,NULL,NULL);
    g_print("key file data :%s\n",data);
    char *sb_file_path = g_build_filename(storage->fs_location,storage->fs_name,"superblock",NULL);
    g_print("sb file path %s\n",sb_file_path);
    bs_file_t file = storage->bs_file_create(storage,"superblock");
    g_print("sb file path 1%s\n",sb_file_path);
    //bs_file_t file = storage->bs_file_open(storage,"superblock",BS_WRITEABLE);
    if(NULL == file){
       g_print("open file :superblock failed");
       g_free(sb_file_path);
       g_option_context_free(context);
       return -1;
    }

    g_print("sb file path 2%s\n",sb_file_path);
    int size = storage->bs_file_append(storage,file,(char*)data,strlen(data)+1);
    if(size != strlen(data)+1){
       g_print("can not write superblock file");
       g_free(sb_file_path);
       g_option_context_free(context);
       return -1;
    }
    g_print("append size:%d\n",size);
	storage->bs_file_flush(storage,file);


    //g_return_if_fail(TRUE == g_file_set_contents(sb_file_path,data,strlen(data),NULL));
    //g_strfreev(v);
    //g_key_file_free(sb_keyfile);
    // g_free(fs_dir_path);
    //g_free(sb_file_path);
    g_print("filesystem :%s mkfs over !!!\n",fsname);
    g_print("location :%s\t",location);
    g_print("block size :%d\t",block_size);
    g_print("segment size :%d\n",seg_size);
    storage->bs_file_close(storage,file);
    //g_free(sb_file_path);
    //g_option_context_free(context);
    return 0;
}
